#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Author : gao
# Time : 2020/7/8 17:44

"""
    文件说明：用sklearn进行分类
"""
import random
import re

from sklearn import naive_bayes as nb
import numpy as np
import CreateData as cd


testPath = 'C:/Users/gao/Desktop/Machine-Learning-in-Action-master/Machine-Learning-in-Action-master/机器学习实战数据集/Ch04-NaiveBayes/'


# 函数说明:接收一个大字符串并将其解析为字符串列表
def textParse(bigString):                                       #将字符串转换为字符列表
    listOfTokens = re.split(r'\W*', bigString)                  #将特殊符号作为切分标志进行字符串切分，即非字母、非数字
    return [tok.lower() for tok in listOfTokens if len(tok) > 2]#除了单个字母，例如大写的I，其它单词变成小写

# 函数说明:测试朴素贝叶斯分类器
def spamTest(clf):
    """

    :param clf: 分类器
    :return:
    """
    docList = []; classList = []; fullText = []
    for i in range(1, 26):                                             #遍历25个txt文件
        wordList = textParse(open(testPath+'email/spam/%d.txt' % i, 'r').read())#读取每个垃圾邮件，并字符串转换成字符串列表
        docList.append(wordList)
        fullText.append(wordList)
        classList.append(1)                                            #标记垃圾邮件，1表示垃圾文件
        wordList = textParse(open(testPath+'email/ham/%d.txt' % i, 'r').read()) #读取每个非垃圾邮件，并字符串转换成字符串列表
        docList.append(wordList)
        fullText.append(wordList)
        classList.append(0)                    		#标记非垃圾邮件，1表示垃圾文件
    vocabList = cd.createVocabList(docList)       		#创建词汇表，不重复
    trainingSet = list(range(50)); testSet = []		#创建存储训练集的索引值的列表和测试集的索引值的列表
    for i in range(10):#从50个邮件中，随机挑选出40个作为训练集,10个做测试集
        randIndex = int(random.uniform(0, len(trainingSet)))              #随机选取索索引值
        testSet.append(trainingSet[randIndex])                            #添加测试集的索引值
        del(trainingSet[randIndex])                                       #在训练集列表中删除添加到测试集的索引值
    trainMat = []; trainClasses = []                                      #创建训练集矩阵和训练集类别标签系向量
    for docIndex in trainingSet:                                          #遍历训练集
        trainMat.append(cd.setOfWords2Vec(vocabList, docList[docIndex]))     #将生成的词集模型添加到训练矩阵中
        trainClasses.append(classList[docIndex])                          #将类别添加到训练集类别标签系向量中
    #pSpam,p1V, p0V = tm.trainModel(np.array(trainMat), np.array(trainClasses))#训练朴素贝叶斯模型
    errorCount = 0                                                        #错误分类计数
    clf.fit(trainMat, trainClasses)
    testMat =[]
    testClasses=[]
    for docIndex in testSet:                                              #遍历测试集
        wordVector = cd.setOfWords2Vec(vocabList, docList[docIndex])         #测试集的词集模型
        testMat.append(wordVector)
        testClasses.append(classList[docIndex])
    res = clf.predict(testMat)
    print('预测结果：',res)
    for i in range(len(res)):
        if  res[i] != testClasses[i]:#如果分类错误
            errorCount += 1                                               #错误计数加1
    print('错误率：%.2f%%' % (float(errorCount) / len(testMat) * 100))


if __name__ == '__main__':
    #trainX,trainY = cd.loadData()
    clf = nb.MultinomialNB()
    spamTest(clf)


